package tmx

import (
	"github.com/beevik/etree"
	"path"
	"sort"
	"strconv"
	"strings"
)

type TmxMap struct {
	Width      int
	Height     int
	Tilewidth  int
	Tileset    []Tileset
	Tileheight int
	Layer      []Layer
}

type Tileset struct {
	Firstgid    int
	Source      string
	TileSetData *TileSetData
}
type Layer struct {
	Id int
	//Data    string
	ImageIndex []string
}

type TileSetData struct {
	Tile []Tile
}

type Tile struct {
	id     int
	Width  int
	Heigth int
	Source string
}

func (self *TmxMap) GetImageForIndex(index int) *Tile {
	if index == 0 {
		return nil
	}
	var tileset *Tileset = nil
	findex := 0
	for _, value := range self.Tileset {
		if index - value.Firstgid>=0 {
			tileset = &value
			findex = value.Firstgid
			break;
		}
	}
	if tileset != nil {
		if index-findex > len(tileset.TileSetData.Tile)-1{
			return nil
		}
		return &tileset.TileSetData.Tile[index-findex]
	}
	return nil
}

type byAge []Tileset
func (p byAge) Len() int {
	return len(p)
}

func (p byAge) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}

func (p byAge) Less(i, j int) bool {
	return p[i].Firstgid > p[j].Firstgid
}

//<tile id="0">
//<image width="1" height="1" source="objects/empty.png"/>
//</tile>

func TileDataXmlParse(filepath string) *TileSetData {
	doc := etree.NewDocument()
	if err := doc.ReadFromFile(filepath); err != nil {
		panic(err)
	}
	tileSetData := new(TileSetData)
	tileset := doc.SelectElement("tileset")
	tiles := tileset.SelectElements("tile")
	tes := make([]Tile, 0, len(tiles))
	basepath, _ := path.Split(filepath)
	for _, tile := range tiles {
		ti := Tile{}
		for _, v := range tile.Attr {
			if v.Key == "id" {
				ti.id, _ = strconv.Atoi(v.Value)
			}
		}
		image := tile.SelectElement("image")

		for _, v := range image.Attr {
			if v.Key == "width" {
				ti.Width, _ = strconv.Atoi(v.Value)
			} else if v.Key == "height" {
				ti.Heigth, _ = strconv.Atoi(v.Value)
			} else if v.Key == "source" {
				ti.Source = path.Join(basepath, v.Value)
			}
		}
		tes = append(tes, ti)
	}
	tileSetData.Tile = tes
	return tileSetData
}

func TmXmlParse(filepath string) *TmxMap {
	filepath = strings.Replace(filepath, "\\", "/", -1)
	doc := etree.NewDocument()
	if err := doc.ReadFromFile(filepath); err != nil {
		panic(err)
	}
	//doc.SelectElement("tileset")
	var tmxMap = new(TmxMap)
	tilemap := doc.SelectElement("map")
	for _, attr := range tilemap.Attr {
		if attr.Key == "width" {
			tmxMap.Width, _ = strconv.Atoi(attr.Value)
		} else if attr.Key == "height" {
			tmxMap.Height, _ = strconv.Atoi(attr.Value)
		} else if attr.Key == "tilewidth" {
			tmxMap.Tilewidth, _ = strconv.Atoi(attr.Value)
		} else if attr.Key == "tileheight" {
			tmxMap.Tileheight, _ = strconv.Atoi(attr.Value)
		}
	}
	tilesets := tilemap.SelectElements("tileset")
	tes := make([]Tileset, 0)
	basepath, _ := path.Split(filepath)
	for _, tileset := range tilesets {
		ti := Tileset{}
		for _, attr := range tileset.Attr {
			if attr.Key == "firstgid" {
				ti.Firstgid, _ = strconv.Atoi(attr.Value)
			} else if attr.Key == "source" {
				ti.Source = attr.Value
			}
		}
		td := TileDataXmlParse(path.Join(basepath, ti.Source))
		ti.TileSetData = td
		tes = append(tes, ti)
	}
	sort.Sort(byAge(tes))
	//sort.Sort(tes)

	tmxMap.Tileset = tes
	laysers := tilemap.SelectElements("layer")
	lys := make([]Layer, 0, len(laysers))
	for _, layer := range laysers {
		ly := Layer{}
		//lys[index]=ly;
		Data := layer.SelectElement("data").Text()
		Data = strings.Replace(Data, "\n", "", -1)
		ly.ImageIndex = strings.Split(Data, ",")
		for _, attr := range layer.Attr {
			if attr.Key == "id" {
				ly.Id, _ = strconv.Atoi(attr.Value)
			}
		}
		lys = append(lys, ly)
	}
	tmxMap.Layer = lys
	return tmxMap
}
